﻿<%@ WebHandler Language="C#" Class="ApsResourceLoadViewHandler" %>

using System;
using System.Web;
using BusinessRule.DTO;
using System.Web.SessionState;
using DatabaseAccess.DBUtility;
using System.Data.OracleClient;
using System.Data;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
using Newtonsoft.Json;
using BusinessRule.Business;
using BusinessRule.IBusiness;
using BusinessRule.BusinessFactory;

//Description: 设备负荷后台处理程序
//Copyright (c) : 通力凯顿（北京）系统集成有限公司
//Writer: zhangrj
//create Date: 2022-05-25
public class ApsResourceLoadViewHandler : IHttpHandler, IRequiresSessionState
{
    ResourceMaintBusiness resourceBusiness = new ResourceMaintBusiness();//设备类
    LimitedCapacityBusiness limitBusiness = new LimitedCapacityBusiness();//排产类
    CurrentUserInfo m_UserInfo;
    public void ProcessRequest(HttpContext context)
    {
        try
        {
            var action = context.Request["action"].ToString();
            m_UserInfo = (CurrentUserInfo)context.Session["CurrentUserInfo"];
            switch (action)
            {
                case "SearchResourceLoad": //查询设备负荷数据
                    SearchResourceLoadDate(context);
                    break;
                default:
                    break;
            }
        }
        catch (Exception ex)
        {
            var result = new uMESProcessResult();
            result.Result = false;
            result.Message = ex.Message;
            context.Response.ContentType = "text/html";
            context.Response.Write(JsonConvert.SerializeObject(result));
        }
    }
    /// <summary>
    /// 查询设备负荷数据
    /// </summary>
    /// <param name="context"></param>
    public void SearchResourceLoadDate(HttpContext context)
    {
        string strStartDate = context.Request["startDate"].ToString();
        string strEndDate = context.Request["endDate"].ToString();
        string resourceNum = context.Request["resourceNum"].ToString();
        if (string.IsNullOrWhiteSpace(strStartDate) || string.IsNullOrWhiteSpace(strEndDate))
        {
            context.Response.Write(JsonConvert.SerializeObject(new uMESProcessResult() { Result = false, Message = "请选择时间范围" }));
            return;
        }
        DataTable dtResource = resourceBusiness.GetResourceInfoForLoad(m_UserInfo.FactoryID, resourceNum);//获取分厂下的设备
        if (dtResource.Rows.Count == 0)
        {
            context.Response.Write(JsonConvert.SerializeObject(new uMESProcessResult() { Result = false, Message = "没有设备数据" }));
            return;
        }
        DataSet ds = new DataSet();
        DateTime startDate = DateTime.Parse(strStartDate);//开始日期
        DateTime endDate = DateTime.Parse(strEndDate);//结束日期
        dtResource.Columns.Add("TOTALVALUE");//总能力值
        dtResource.Columns.Add("USERVALUE");//总使用能力
        dtResource.Columns.Add("SURPLUSVALUE");//剩余能力
        dtResource.Columns.Add("MAXINTERVAL");//最大间隙
        dtResource.Columns.Add("INTERVALDATE");//间隙日期
        dtResource.Columns.Add("AVAILDRATE");//利用率
        dtResource.Columns.Add("WEEKTOTALVALUE");//周能力值
        dtResource.Columns.Add("WEEKUSERVALUE");//周使用能力
        int days = GetDateDiffDays(startDate, endDate);
        decimal week = Math.Floor((decimal)(days / 7)) + 1;
        for (int i = 1; i <= week; i++)
        {
            dtResource.Columns.Add("Week" + i);//周数
        }
        DataTable dtLine = GetResourceLineDate(ref dtResource, startDate, endDate);
        dtLine.TableName = "dtLine";//总负荷折线图数据
        ds.Tables.Add(dtLine);
        //计算每台设备的其他属性
        foreach (DataRow item in dtResource.Rows)
        {
            double total = string.IsNullOrWhiteSpace(item["totalValue"].ToString()) ? 0 : int.Parse(item["totalValue"].ToString());
            double use = string.IsNullOrWhiteSpace(item["userValue"].ToString()) ? 0 : int.Parse(item["userValue"].ToString());
            item["surplusValue"] = total - use;//剩余能力
            item["availdRate"] = total == 0 ? "0%" : ((use / total) * 100).ToString("0.00") + "%";//利用率
        }
        dtResource.TableName = "dtResource";//设备负荷表格数据
        ds.Tables.Add(dtResource);
        context.Response.Write(JsonConvert.SerializeObject(new uMESProcessResult() { Result = true, DBDataSet = ds }));
    }
    /// <summary>
    /// 获取设备时间范围内的利用率
    /// </summary>
    /// <param name="context"></param>
    public DataTable GetResourceLineDate(ref DataTable dtResource, DateTime startDate, DateTime endDate)
    {
        DataTable dtLine = new DataTable();//分厂下所有设备的利用率折线图数据
        dtLine.Columns.Add("xData");
        dtLine.Columns.Add("yData");
        double totalCapabilityValue = 0, totalUserValue = 0;//一天总的设备能力值，一天总的设备使用值
        int weekDay = 1, weeks = 1;//周的天数计数器，周计数器
        while (startDate <= endDate)
        {
            DataRow dr = dtLine.NewRow();
            dr["xData"] = startDate.ToString("MM/dd");
            if (resourceBusiness.IsHolidayDate(m_UserInfo.FactoryID, startDate, 0))//如果分厂这天是假期，所有设备不用计算，跳过
            {
                dr["yData"] = 0;
                dtLine.Rows.Add(dr);
                startDate = startDate.AddDays(1);
                weekDay++;
                continue;
            }
            totalCapabilityValue = 0;//一天时间内的所有设备总能力值
            totalUserValue = 0;//一天时间内的所有设备总使用值
            int week = (int)Math.Floor((decimal)(weekDay / 7)) + 1;//实时的周计数器
            foreach (DataRow item in dtResource.Rows)//循环设备
            {
                Tuple<int, int> validMins = GetResourceVaildMinsValue(item["resourceid"].ToString(), startDate);
                totalCapabilityValue += validMins.Item1;//能力值
                totalUserValue += validMins.Item2;//使用值
                //添加每一个设备的当前日期的能力
                item["totalValue"] = string.IsNullOrWhiteSpace(item["totalValue"].ToString()) ? validMins.Item1 : int.Parse(item["totalValue"].ToString()) + validMins.Item1;
                item["userValue"] = string.IsNullOrWhiteSpace(item["userValue"].ToString()) ? validMins.Item2 : int.Parse(item["userValue"].ToString()) + validMins.Item2;
                //计算周利用率
                if (week == weeks && startDate < endDate) //如果当前日期的周数等于当前周，则累加设备能力值
                {
                    item["weekTotalValue"] = string.IsNullOrWhiteSpace(item["weekTotalValue"].ToString()) ? validMins.Item1 : int.Parse(item["weekTotalValue"].ToString()) + validMins.Item1;
                    item["weekUserValue"] = string.IsNullOrWhiteSpace(item["weekUserValue"].ToString()) ? validMins.Item2 : int.Parse(item["weekUserValue"].ToString()) + validMins.Item2;
                }
                else
                {
                    double total = string.IsNullOrWhiteSpace(item["weekTotalValue"].ToString()) ? 0 : int.Parse(item["weekTotalValue"].ToString());
                    double use = string.IsNullOrWhiteSpace(item["weekUserValue"].ToString()) ? 0 : int.Parse(item["weekUserValue"].ToString());
                    item["Week" + weeks] = total == 0 ? "0%" : ((use / total) * 100).ToString("0.00") + "%";//计算该设备这周的利用率
                    item["weekTotalValue"] = validMins.Item1;//重置周能力值
                    item["weekUserValue"] = validMins.Item2;//重置周使用值
                }
            }
            if (weeks != week)//如果当前周不等于实时周
            {
                weeks = week;//移动到下一周
            }
            double db = totalCapabilityValue != 0 ? (totalUserValue / totalCapabilityValue) * 100 : 0;
            dr["yData"] = db.ToString("0.00");
            dtLine.Rows.Add(dr);
            startDate = startDate.AddDays(1);
            weekDay++;
        }
        return dtLine;
    }

    /// <summary>
    /// 获取某天的设备总能力值，使用值
    /// </summary>
    /// <param name="resourceId">设备ID</param>
    /// <param name="currDate">日期</param>
    /// <returns></returns>
    private Tuple<int, int> GetResourceVaildMinsValue(string resourceId, DateTime currDate)
    {
        int totalValue = 0, userValue = 0;
        DataSet ds = resourceBusiness.GetApsResourceLinkDt(resourceId);
        DataTable dtWorkshift = ds.Tables["dtWorkshift"];//班次记录
        DataTable dtResourceUpKeep = ds.Tables["dtResourceUpKeep"];//保养记录
        DataTable dtReportDispatchDate = ds.Tables["dtReportDispatchDate"];//设备运行的时间记录
        DateTime nextDate = currDate.AddDays(1);//获取今天的最后时辰
        if (dtWorkshift.Rows.Count > 0)
        {
            currDate = DateTime.Parse(currDate.ToString("yyyy-MM-dd") + " " + dtWorkshift.Rows[0]["startdate"].ToString());
            nextDate = DateTime.Parse(currDate.ToString("yyyy-MM-dd") + " " + dtWorkshift.Rows[0]["enddate"].ToString());
        }
        totalValue = GetVaildMins(dtResourceUpKeep, currDate, nextDate);//获取能力值
        //如果设备这天是假期，只需要能力值，不计算使用值
        if (resourceBusiness.IsHolidayDate(resourceId, currDate, 1))
        {
            return new Tuple<int, int>(totalValue, userValue);
        }
        //没有任务接收、报工数据。不计算计算使用能力
        if (string.IsNullOrWhiteSpace(dtReportDispatchDate.Rows[0]["startDate"].ToString())&&string.IsNullOrWhiteSpace(dtReportDispatchDate.Rows[0]["endDate"].ToString()))
        {
             return new Tuple<int, int>(totalValue, userValue);
        }
        //能力值不为0，计算使用能力
        if (totalValue > 0)
        {
            //如果接收时间不为空，则判定接收时间是否在当前时间内
            if (!string.IsNullOrWhiteSpace(dtReportDispatchDate.Rows[0]["startDate"].ToString()))
            {
                DateTime startDate = DateTime.Parse(dtReportDispatchDate.Rows[0]["startDate"].ToString());
                if (startDate > nextDate) //如果设备开始日期大于当前日期的结束时间，则不计算使用能力
                {
                    return new Tuple<int, int>(totalValue, userValue);
                }
                else if (startDate > currDate && startDate < nextDate)
                {
                    currDate = startDate;
                }
            }
            //如果报工时间不为空，则判定报工时间是否在当前时间内
            if (!string.IsNullOrWhiteSpace(dtReportDispatchDate.Rows[0]["endDate"].ToString()))
            {
                DateTime endDate = DateTime.Parse(dtReportDispatchDate.Rows[0]["endDate"].ToString());
                if (endDate < currDate)//如果设备结束日期小于当前日期的开始时间，则不计算使用能力
                {
                    return new Tuple<int, int>(totalValue, userValue);
                }
                else if (endDate > currDate && endDate < nextDate)
                {
                    nextDate = endDate;
                }
            }
            userValue = GetVaildMins(dtResourceUpKeep, currDate, nextDate);//获取使用值
        }
        return new Tuple<int, int>(totalValue, userValue);
    }
    /// <summary>
    /// 排除保养时间,获取有效的分钟
    /// </summary>
    /// <param name="dtResourceUpKeep">设备保养记录</param>
    /// <param name="currDate">有效开始日期</param>
    /// <param name="currDate">有效结束日期</param>
    /// <returns></returns>
    private int GetVaildMins(DataTable dtResourceUpKeep, DateTime currDate, DateTime nextDate)
    {
        int value = (int)limitBusiness.GetDifferMins(nextDate, currDate);//获取时间段的分钟
        foreach (DataRow item in dtResourceUpKeep.Rows) //排除保养记录时间
        {
            if (value == 0)
            {
                break;
            }
            DateTime dTime1 = DateTime.Parse(item["upkeepstartdate"].ToString());
            DateTime dTime2 = DateTime.Parse(item["upkeependdate"].ToString());
            if (currDate >= dTime2 || nextDate <= dTime1) //如果开始时间大于保养结束时间或者结束时间小于保养开始时间，则跳过
            {
                continue;
            }
            else if (currDate <= dTime1 && nextDate >= dTime2)
            {
                int invalidValue = (int)limitBusiness.GetDifferMins(dTime2, dTime1);//获取无效时间段的分钟
                value -= invalidValue;
            }
            else if (currDate >= dTime1 && nextDate <= dTime2)
            {
                value = 0;
            }
            else if (currDate >= dTime1 && nextDate >= dTime2)
            {
                int invalidValue = (int)limitBusiness.GetDifferMins(dTime2, currDate);//获取无效时间段的分钟
                value -= invalidValue;
            }
            else if (currDate <= dTime1 && nextDate <= dTime2)
            {
                int invalidValue = (int)limitBusiness.GetDifferMins(nextDate, dTime1);//获取无效时间段的分钟
                value -= invalidValue;
            }
        }
        return value;
    }
    /// <summary>
    /// 计算两个日期相隔天数
    /// </summary>
    /// <param name="time1"></param>
    /// <param name="time2"></param>
    /// <returns></returns>
    private int GetDateDiffDays(DateTime time1, DateTime time2)
    {
        TimeSpan ts1 = new TimeSpan(time1.Ticks);
        TimeSpan ts2 = new TimeSpan(time2.Ticks);
        TimeSpan ts = ts1.Subtract(ts2).Duration();
        return ts.Days;
    }


    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

}